package com.ytf.test.third;

/**
 * @author: YTF
 * @date: 2024/9/12 15:33
 * @version: 1.0
 * @description: 直接常量
 */
public class Literals {
    public static void main(String[] args) {
        int i1 = 0x2f;
        System.out.println("i1: " + Integer.toBinaryString(i1));
        int i2 = 0x2f;
        System.out.println("i2: " + Integer.toBinaryString(i2));
        int i3 = 0177;
        System.out.println("i3: " + Integer.toBinaryString(i3));
        char c1 = 0xffff;
        System.out.println("c1: " + Integer.toBinaryString(c1));
        byte b1 = 0x7f;
        System.out.println("b1: " + Integer.toBinaryString(b1));
        short s1 = 0x7fff;
        System.out.println("s1: " + Integer.toBinaryString(s1));
        long l1 = 200L;
        long l2 = 200l; // 可以用但小l和1很难区分建议使用L; but can be confusing
        long l3 = 200;
        System.out.println("l1: " + Long.toBinaryString(l1));
        float f1=1;
        float f2=1.1F;
        float f3=1.1f;
        double d1 = 1d;
        double d2 = 1D;
        /*
         百度搜索的不知道是否正确，现阶段没理解
            int intBits = Float.floatToIntBits(f1);
            String binaryString = Integer.toBinaryString(intBits);
            System.out.println("float 二进制表示：" + binaryString);
            long longBits = Double.doubleToLongBits(d1);
            System.out.println("double 二进制表示："+Long.toBinaryString(longBits));
        */
        /**
         * Output:
         * i1: 101111
         * i2: 101111
         * i3: 1111111
         * c1: 1111111111111111
         * b1: 1111111
         * s1: 111111111111111
         * l1: 11001000
         * 转换二进制利用了 >>> 使效率提升了很多 太牛逼了
         */
        // 下面内容是自己看着玩的 模仿整数转换二进制
        // imitateToBinaryStringTest();
    }
    static void imitateToBinaryStringTest(){
        String str = toBinaryString(47);
        System.out.println(str);
    }

    final static char[] digits = {
            '0' , '1' , '2' , '3' , '4' , '5' ,
            '6' , '7' , '8' , '9' , 'a' , 'b' ,
            'c' , 'd' , 'e' , 'f' , 'g' , 'h' ,
            'i' , 'j' , 'k' , 'l' , 'm' , 'n' ,
            'o' , 'p' , 'q' , 'r' , 's' , 't' ,
            'u' , 'v' , 'w' , 'x' , 'y' , 'z'
    };

    public static String toBinaryString(int i) {
        return toUnsignedString0(i, 1);
    }
    private static String toUnsignedString0(int val, int shift) {
        // assert shift > 0 && shift <=5 : "Illegal shift value";
        //通过numberOfLeadingZeros 知道左边右多少零就可以得出需要建立多大的char数组
        int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);
        // Math.max 返回大的那个数字，保证数组内存大小不为零
        int chars = Math.max(((mag + (shift - 1)) / shift), 1);
        char[] buf = new char[chars];

        formatUnsignedInt(val, shift, buf, 0, chars);

        // Use special constructor which takes over "buf".
        return new String(buf);
    }


    static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {
        int charPos = len;
        int radix = 1 << shift;
        int mask = radix - 1;
        do {
            // "&"（按位与）：当两个相应的二进制位都为1时，结果为1，否则为0。
            System.out.println("val:"+val+" mask:"+mask+" val & mask:"+(val & mask)+" digits[val & mask]"+(digits[val & mask]));
            buf[offset + --charPos] = digits[val & mask];
            // >>>是无符号右移运算符，用于将二进制数向右移动指定的位数，并在左侧填充0。 这里就是和除2一样
            val >>>= shift;
        } while (val != 0 && charPos > 0);

        return charPos;
    }
    /**
     * 计算前导零
     * >> 右移补充符号位 >>>强制右移补充0
     *
     * @param i
     * @return
     */
    public static int numberOfLeadingZeros(int i) {
        // HD, Figure 5-6
        if (i == 0)
            // 二进制为零直接返回位数
            return 32;
        int n = 1;
        if (i >>> 16 == 0) {
            n += 16;
            i <<= 16;
        }
        if (i >>> 24 == 0) {
            n += 8;
            i <<= 8;
        }
        if (i >>> 28 == 0) {
            n += 4;
            i <<= 4;
        }
        if (i >>> 30 == 0) {
            n += 2;
            i <<= 2;
        }
        n -= i >>> 31;
        return n;
    }
}
